package it.koutifaris.travianmap.dal.sqlservices.travianserver;

import it.koutifaris.travianmap.dal.TravianServerService;
import it.koutifaris.travianmap.dal.sqlservices.SqlMapDbHelper;
import it.koutifaris.travianmap.dal.sqlservices.travianserver.TravianServerContract.TravianServers;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class SqlTravianServerService implements TravianServerService {

	private final SQLiteDatabase db;

	public SqlTravianServerService(SQLiteDatabase db) {
		this.db = db;
	}

	@Override
	public TravianServer newServer(String server) {
		TravianServerImpl result = new TravianServerImpl(server, null);

		ContentValues contentValues = createContentValues(server);

		db.insertWithOnConflict(TravianServers.TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);

		return result;
	}

	private ContentValues createContentValues(String server) {
		ContentValues contentValues = new ContentValues();
		contentValues.put(TravianServers.COLUMN_NAME_SERVER, server);
		contentValues.put(TravianServers.COLUMN_NAME_LAST_UPDATE, getDefaultTimeMillis());

		return contentValues;
	}

	private long getDefaultTimeMillis() {
		return 0;
	}

	@Override
	public List<TravianServer> listServers() {
		String[] columns = getAllColumns();

		Cursor cursor = db.query(TravianServers.TABLE_NAME, columns, null, null, null, null, null);

		return getServersFromCursor(cursor);
	}

	private List<TravianServer> getServersFromCursor(Cursor cursor) {
		List<TravianServer> servers = new ArrayList<TravianServer>();

		while (cursor.moveToNext()) {
			servers.add(getServerFromCursor(cursor));
		}
		cursor.close();

		return servers;
	}

	private TravianServer getServerFromCursor(Cursor cursor) {
		if (cursor.isAfterLast()) {
			return null;
		}

		String server = cursor.getString(cursor.getColumnIndex(TravianServers.COLUMN_NAME_SERVER));
		long lastUpdate = cursor.getLong(cursor.getColumnIndex(TravianServers.COLUMN_NAME_LAST_UPDATE));

		return new TravianServerImpl(server, (lastUpdate > 0) ? new Date(lastUpdate) : null);
	}

	@Override
	public TravianServer getServer(String server) {
		String[] columns = getAllColumns();

		String whereCondition = TravianServers.COLUMN_NAME_SERVER + " = ?";
		String[] whereArgs = { server };

		Cursor cursor = db.query(TravianServers.TABLE_NAME, columns, whereCondition, whereArgs, null, null, null);
		cursor.moveToNext();
		TravianServer result = getServerFromCursor(cursor);
		cursor.close();

		return result;
	}

	private String[] getAllColumns() {
		String[] columns = { TravianServers.COLUMN_NAME_SERVER, TravianServers.COLUMN_NAME_LAST_UPDATE };
		return columns;
	}

	@Override
	public TravianServer updateServer(String server, Date lastUpdate) {
		ContentValues contentValues = new ContentValues();
		contentValues.put(TravianServers.COLUMN_NAME_LAST_UPDATE, lastUpdate.getTime());

		String where = TravianServers.COLUMN_NAME_SERVER + " = ?";
		String[] whereArgs = { server };

		db.update(TravianServers.TABLE_NAME, contentValues, where, whereArgs);

		return getServer(server);
	}

	@Override
	public boolean dropServer(Context context, TravianServer server) {
		boolean deleted = context.deleteDatabase(SqlMapDbHelper.getDbName(server.getServerId()));

		String whereClause = TravianServers.COLUMN_NAME_SERVER + " = ?";
		String[] whereArgs = { server.getServerId() };
		int numRowDeleted = db.delete(TravianServers.TABLE_NAME, whereClause, whereArgs);

		return deleted && (numRowDeleted > 0);
	}

	@Override
	public void dropAllServers(Context context) {
		List<TravianServer> listServers = this.listServers();
		for (TravianServer travianServer : listServers) {
			dropServer(context, travianServer);
		}
	}

	@Override
	public void close() {
		db.close();
	}
}
